
package org.gamma.applet;

import java.applet.Applet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import netscape.javascript.JSObject;

public abstract class GammaApplet extends Applet {
	private static final long serialVersionUID = -3498000353545706801L;
	private ExecutorService threadPool = null;
	private static final Object LOCK = new Object();
    
    public void publish(JSObject input, int index) {
        JSObject output = null;
        synchronized(LOCK) { // Browser access is typically not thread-safe.
            JSObject win = (JSObject)JSObject.getWindow(this);
            JSObject gamma = (JSObject)win.getMember("gamma");
            JSObject messages = (JSObject)gamma.getMember("messages");
            output = (JSObject)messages.getSlot(index);
        }
        
        GammaTask task = taskFor(input);
        task.setApplet(this);
        task.setIndex(index);
        task.setInput(input);
        task.setOutput(output);
        
        getThreadPool().execute(task);
    }
    
    /**
     * Derived GammaApplets should examine the input and return 
     * an appropriate derivation of GammaTask.
     * @param input
     * @return
     */
    protected abstract GammaTask taskFor(JSObject input);

    protected void onReady(int index) {
        Object[] objsAppendArgs = new Object[1];
        objsAppendArgs[0] = index;
        synchronized(LOCK) { // Browser access is typically not thread-safe.
            JSObject win = (JSObject)JSObject.getWindow(this);
            win.call("ready", objsAppendArgs);
        }
    }

    private ExecutorService getThreadPool() {
    	if(threadPool == null) {
    		threadPool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
    	}
        return threadPool;
    }
}
